package com.enjoyor.soa.traffic.server.tsms.dubbo.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.enjoyor.soa.traffic.server.tsms.common.RehearseGlobal;
import com.enjoyor.soa.traffic.server.tsms.handler.InitializeHandler;
import com.enjoyor.soa.traffic.server.tsms.thead.RehearseThead;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.enjoyor.soa.traffic.api.service.dubbo.gps.PositionService;
import com.enjoyor.soa.traffic.api.service.dubbo.tsms.IDubboRouteInfoService;
import com.enjoyor.soa.traffic.api.service.dubbo.tsms.IDubboSchemeActionService;
import com.enjoyor.soa.traffic.core.tsms.domain.RltRouteDevice;
import com.enjoyor.soa.traffic.core.tsms.domain.RouteInfo;
import com.enjoyor.soa.traffic.core.tsms.domain.RoutePoint;
import com.enjoyor.soa.traffic.core.tsms.enums.EnumDicPublic;
import com.enjoyor.soa.traffic.core.tsms.service.IRltRouteDeviceService;
import com.enjoyor.soa.traffic.core.tsms.service.IRouteInfoService;
import com.enjoyor.soa.traffic.util.enums.EnumAppCode;
import com.enjoyor.soa.traffic.util.helper.GeoToolsHelper;
import com.enjoyor.soa.traffic.util.helper.GeomtryHelper;
import com.enjoyor.soa.traffic.util.helper.ReflectHelper;
import com.enjoyor.soa.traffic.util.helper.ResultHelper;
import com.enjoyor.soa.traffic.util.helper.TimeHelper;
import com.enjoyor.soa.traffic.util.pojo.ResultPojo;

import oracle.spatial.geometry.JGeometry;

@Service(version = "1.0.0", timeout = 4000)
public class DubboSchemeActionService implements IDubboSchemeActionService {
	@Reference(version = "1.0.0", timeout = 10000)
	private IDubboRouteInfoService iDubboRouteInfoService;

	@Reference( timeout = 10000) //gps的dubbo服务未开启
	private PositionService positionService;
	@Autowired
	private IRouteInfoService iRouteInfoService;
	@Autowired
	private IRltRouteDeviceService iRltRouteDeviceService;

	GeoToolsHelper geoToolsHelper = new GeoToolsHelper(); 
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	@Value("${route.split.time}")
    private int routeSplitTime;
	
	public static int maxSpeed;
	@Value("${task.execute.max.speed}")
	public void setMaxSpeed(int maxSpeed) {
		this.maxSpeed = maxSpeed;
	}

	public static int deviateLength;
	@Value("${task.execute.deviate.length}")
	public void setDeviateLength(int length) {
		this.deviateLength = length;
	}
	public static int deviateTimes;
	@Value("${task.execute.deviate.times}")
	public void setDeviateTimes(int times) {
		this.deviateTimes = times;
	}
	public static int normalTimes;
	@Value("${task.execute.normal.times}")
	public void setNormalTimes(int normalTimes) {
		this.normalTimes = normalTimes;
	}
	public static int nocoordTime;
	@Value("${task.execute.nocoord.time}")
	public void setNocoordTime(int nocoordTime) {
		this.nocoordTime = nocoordTime;
	}
	public static int delayTime;
	@Value("${task.execute.delay.time}")
	public void setDelayTime(int delay) {
		this.delayTime = delay;
	}
	public static int lockDistance;
	@Value("${device.lock.distance}")
	public void setLockDistance(int distance) {
		this.lockDistance = distance;
	}
	public static int clashDistance;
	@Value("${route.clash.distance}")
	public void setClashDistance(int clashDistance) {
		this.clashDistance = clashDistance;
	}
	
	@Override
	public void getPushServer(String routeId, String executeTaskId, String state, String positionDeviceId, String personName) {
		Map<String,String> m=new HashMap<>();
		m.put("executeTaskId",executeTaskId);
		m.put("routeId",routeId);
		m.put("state",state);
		m.put("positionDeviceId",positionDeviceId);
		m.put("personName",personName);
		InitializeHandler.getInstance().handle(m);
	}
	
	@SuppressWarnings({ "static-access", "unchecked" })
	@Override
	public ResultPojo changeFastRoute(String executeTaskId, String routeId, String newGeoStr, String personName) {
		ResultPojo resultPojo = new ResultPojo();
		try {
			List<RouteInfo> routeInfoList = iRouteInfoService.getRouteInfoList(routeId, null, null, null, null, null);
			if(null != routeInfoList && routeInfoList.size() > 0) {
				RouteInfo routeInfo = routeInfoList.get(0);
				String taskId = routeInfo.getTaskId();
				JGeometry geoold = routeInfo.getRouteGeo();
				//String geonewStr = routeInfoDto.getStrArea();
				JGeometry geonew = GeomtryHelper.getGeomWithGson(newGeoStr);
				Map<String, Object> geoHelperMap = geoToolsHelper.buildNewLine(geoold,geonew);//合并成新线路
				String newLineString = (String)geoHelperMap.get("newLineString");//新线路
				JGeometry newLineGeom = GeomtryHelper.getGeomWithGson(newLineString);
				Map<String, Object> firstPoint = (Map<String, Object>)geoHelperMap.get("firstPoint");//两线路连接起始点
				//double firstX = (double)firstPoint.get("x");
				//double firstY = (double)firstPoint.get("y");
				double firstStartLength = (double)firstPoint.get("distanceStartPointLength");
				Map<String, Object> lastPoint = (Map<String, Object>)geoHelperMap.get("lastPoint");//两线路连接终点
				//double lastX = (double)lastPoint.get("x");
				//double lastY = (double)lastPoint.get("y");
				double lastStartLength = (double)lastPoint.get("distanceStartPointLength");
				//把执行线路改为备用
				iRouteInfoService.changeTypeToStandby(taskId);
				
				RouteInfo routeInfoNew =  ReflectHelper.beanToBean(routeInfo, RouteInfo.class);
				routeInfoNew.setRouteTypeId(EnumDicPublic.ROUTE_EXECUTE.getKey());
				routeInfoNew.setRouteTypeName(EnumDicPublic.ROUTE_EXECUTE.getValue());
				routeInfoNew.setStrArea(newLineString);
				routeInfoNew.setRouteGeo(newLineGeom);
				double[] lastPointNew = geoToolsHelper.lastGeometryXY(newLineGeom);//新线路的最后坐标
				Map<String, Object> lastMapNew = geoToolsHelper.getProjectionPoint(newLineGeom, lastPointNew[0], lastPointNew[1]);
				Double routeLength = (Double)lastMapNew.get("distanceStartPointLength");//新线路长度
				routeInfoNew.setRouteLength(Integer.valueOf(routeLength.intValue()));
				List<RoutePoint> routePointListOld = routeInfo.getRoutePointList();
				List<RoutePoint> routePointList = ReflectHelper.listToList(routePointListOld, RoutePoint.class);
				List<RoutePoint> routePointListNew = new ArrayList<RoutePoint>();
				int lastIndex = 0;
				boolean isEditSpeed = true;
				for(int i = 0; i < routePointList.size(); i++) {
					RoutePoint routePoint = routePointList.get(i);
					int pointLength = routePoint.getPointLength().intValue();
					//起始接口之前的途径点信息不变，终点接口的途径点距离重新计算（第一个速度重新计算）
					if(pointLength < firstStartLength) {
						routePointListNew.add(routePoint);
						lastIndex = i;
					}else if(pointLength > lastStartLength){
						//重新计算该途径点距新线路起点距离
						double pointX = routePoint.getPointX();
						double pointY = routePoint.getPointY();
						Map<String, Object> routePointMap = geoToolsHelper.getProjectionPoint(newLineGeom, pointX, pointY);
						Double pointLengthNew = (Double)routePointMap.get("distanceStartPointLength");
						routePoint.setPointLength(Integer.valueOf(pointLengthNew.intValue()));
						if(isEditSpeed) {
							isEditSpeed = false;
							String planTimeLast = routePointList.get(lastIndex).getPlanTime();//上个途径点离开时间
							int pointLengthLast = routePointList.get(lastIndex).getPointLength().intValue();//上个途径点距起点距离
							String planTime = routePoint.getPlanTime();//该途径点点离开时间
							Double parkTime = routePoint.getParkTime();//该途径点点停留时间
							String newDateTime = TimeHelper.dateToShortString(new Date());//当前日期
							String planTimeLastS = newDateTime + " " + planTimeLast + ":00";
							long planTimeLastL = TimeHelper.StringToDateTime(planTimeLastS, "yyyy-MM-dd HH:mm:ss");//转化为时间戳
							String planTimeS = newDateTime + " " + planTime + ":00";
							long planTimeL = TimeHelper.StringToDateTime(planTimeS, "yyyy-MM-dd HH:mm:ss");//转化为时间戳
							double speedNew = (pointLengthNew-pointLengthLast)/(planTimeL-planTimeLastL-parkTime*60*1000)/1000;
							routePoint.setSpeed((double)(Math.round(speedNew * 100) / 100));//更新途径点速度
							routePoint.setSectionLength(Integer.valueOf(pointLengthNew.intValue()) - pointLengthLast);
						}
						routePointListNew.add(routePoint);
					}
				}
				//保存新线路信息
				String routeIdNew = iRouteInfoService.addRouteInfo(routeInfoNew, personName);
				
				List<RltRouteDevice> rltDeviceListOld = routeInfo.getRltRouteDeviceList();
				List<RltRouteDevice> rltDeviceList = ReflectHelper.listToList(rltDeviceListOld, RltRouteDevice.class);
				List<RltRouteDevice> rltDeviceListNew = new ArrayList<RltRouteDevice>();
				for(RltRouteDevice rltRouteDevice : rltDeviceList) {
					int deviceLength = rltRouteDevice.getDeviceLength().intValue();
					rltRouteDevice.setRouteId(routeIdNew);//新线路编号
					if(deviceLength < firstStartLength) {
						rltDeviceListNew.add(rltRouteDevice);
					}else if(deviceLength > lastStartLength){
						//重新计算该设备距新线路起点距离
						double deviceX = rltRouteDevice.getDeviceX();
						double deviceY = rltRouteDevice.getDeviceY();
						Map<String, Object> rltRouteDeviceMap = geoToolsHelper.getProjectionPoint(newLineGeom, deviceX, deviceY);
						Double deviceLengthNew = (Double)rltRouteDeviceMap.get("distanceStartPointLength");
						rltRouteDevice.setDeviceLength(Integer.valueOf(deviceLengthNew.intValue()));
						rltDeviceListNew.add(rltRouteDevice);
					}
				}
				//保存关联设备信息
				iRltRouteDeviceService.rltRouteDeviceListBase(rltDeviceListNew, personName);
				
				//切换线路继续执行
				this.getPushServer(routeIdNew, executeTaskId, "change", null, personName);
				resultPojo = ResultHelper.getResult(routeIdNew);
			}else {
				return ResultHelper.getResult(EnumAppCode.PARAM_ERR, "获取原线路信息失败！");
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return resultPojo;
	}
	
	/***
	 * 获取方案执行线程List
	 * @return 
	 */
	@Override
	public ResultPojo getActionDataPoolList() {
		List<Map<String,Object>> resultList = new ArrayList<Map<String,Object>>();
		Map<String, Map<String,Object>> actionDataMap = RehearseGlobal.ActionDataPool;
    	for (Map.Entry<String, Map<String, Object>> m : actionDataMap.entrySet()) {
    		Map<String,Object> tempMap = new HashMap<String,Object>();
    		String executeTaskId = m.getKey();
			String taskName = (String)RehearseGlobal.ActionDataPool.get(executeTaskId).get("taskName");
			tempMap.put("executeTaskId", executeTaskId);
			tempMap.put("taskName", taskName);
			resultList.add(tempMap);
    	}
    	return ResultHelper.getResult(resultList);
	}
	
	/***
	 * 清除方案执行线程
	 * @return 
	 */
	@Override
	public ResultPojo clearActionDataPool(String executeTaskId) {
		ResultPojo resultPojo = new ResultPojo();
		boolean flag = false;
		if(null != executeTaskId && !"".equals(executeTaskId)) {
			Map<String, Map<String,Object>> actionDataMap = RehearseGlobal.ActionDataPool;
	    	for (Map.Entry<String, Map<String, Object>> m : actionDataMap.entrySet()) {
	    		String key = m.getKey();
	    		if(key.equals(executeTaskId)) {
	    			RehearseGlobal.ActionDataPool.get(key).put("stop",true);
	        		if(RehearseGlobal.ActionDataPool.get(key).get("listerid")!=null){//删除定位订阅
	        			long listerid = Long.parseLong(RehearseGlobal.ActionDataPool.get(key).get("listerid").toString());
	        			InitializeHandler.getInstance().getPositionService().removeListener(listerid);
	    			}
	    			if(RehearseGlobal.ActionDataPool.get(key).get("listenerIdPass")!=null){//删除卡口过车数据订阅
	    				InitializeHandler.getInstance().getVehicleCallbackService().removeVehiclePassListener(key);
	    			}
	    			RehearseGlobal.ActionDataPool.remove(key);
	    			flag = true;
	    			break;
	    		}
	    	}
		}
		if(!flag) {
			resultPojo = ResultHelper.getResult(EnumAppCode.ILLEGAL_ARGUMEN, "删除执行线程失败:参数为空或者对应线程不存在!");
		}else {
			resultPojo = ResultHelper.getResult("删除执行线程成功!");
		}
    	return resultPojo;
	}
	
	/***
	 * 获取方案执行线程List
	 * @return 
	 */
	@Override
	public ResultPojo getRehearseDataPoolList() {
		List<Map<String,Object>> resultList = new ArrayList<Map<String,Object>>();
		Iterator<RehearseThead> iterator = RehearseGlobal.rehearseThreadlist.iterator();
		while (iterator.hasNext()) {
			RehearseThead thread = iterator.next();
			Map<String,Object> tempMap = new HashMap<String,Object>();
			String threadName = thread.getName();
			int threadState = thread.getStatus();
			String executeDate = thread.getExecuteDate();
			tempMap.put("threadName", threadName);
			tempMap.put("threadState", threadState);
			tempMap.put("executeDate", executeDate);
			resultList.add(tempMap);
		}
    	return ResultHelper.getResult(resultList);
	}
	
	/***
	 * 清除方案执行线程
	 * @return 
	 */
	@Override
	public ResultPojo clearRehearseDataPool(String threadName) {
		ResultPojo resultPojo = new ResultPojo();
		boolean flag = false;
		if(null != threadName && !"".equals(threadName)) {
			Iterator<RehearseThead> iterator = RehearseGlobal.rehearseThreadlist.iterator();
			while (iterator.hasNext()) {
				RehearseThead thread = iterator.next();
				if (thread.getName().equals(threadName) && (thread.getState() == Thread.State.WAITING || thread.getState() == Thread.State.TIMED_WAITING)) {
					thread.interrupt();
					iterator.remove();
					flag = false;
				}
			}
		}
		if(!flag) {
			resultPojo = ResultHelper.getResult(EnumAppCode.ILLEGAL_ARGUMEN, "删除预演线程失败:参数为空或者对应线程不存在!");
		}else {
			resultPojo = ResultHelper.getResult("删除预演线程成功!");
		}
    	return resultPojo;
	}
}
